package com.tianyu.inspection.service;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tianyu.inspection.common.component.MapperModel;
import com.tianyu.inspection.common.model.PageModel;
import com.tianyu.inspection.entity.*;
import com.tianyu.inspection.entity.model.OperateMo;
import com.tianyu.inspection.entity.model.QueryMo;
import com.tianyu.inspection.mapper.*;
import com.tianyu.inspection.service.api.IGeneralFacilitiesService;
import io.ocs.model.OcsSimpleModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

/**********************************
 * @Author YSW
 * @Description 通用设施服务
 * @Date 2021/1/18 - 09:40
 **********************************/

@Service
@Slf4j
public class GeneralFacilitiesServiceImpl implements IGeneralFacilitiesService {

    @Resource
    private MapperModel mapperModel;

    @Resource
    private GeneralFacilitiesMapper generalFacilitiesMapper;

    @Resource
    private PileCardMapper pileCardMapper;

    @Resource
    private HighConsequenceAreasMapper highConsequenceAreasMapper;

    @Resource
    private ConstructionUnitsMapper constructionUnitsMapper;

    @Resource
    private CameraMapper cameraMapper;

    @Resource
    private OcsSimpleModel ocsSimpleModel;


    /**
     * JSON格式基础信息导入
     *
     * @param jsonObj json对象
     * @return
     */
    @Override
    public boolean baseMsSaveByJson(JSONObject jsonObj) {
        final Boolean isMultiple = jsonObj.getBoolean("isMultiple");
        final Integer messageType = jsonObj.getInteger("messageType");
        final Integer projectId = jsonObj.getInteger("projectId");
        final Integer pipelineId = jsonObj.getInteger("pipelineId");
        final Integer dataType = jsonObj.getInteger("typeId");
        if (isMultiple) {
            final JSONArray data = jsonObj.getJSONArray("data");
            return doSaveMsMulti(messageType, projectId, pipelineId, data, dataType);
        } else {
            final JSONObject data = jsonObj.getJSONObject("data");
            final String name = data.getString("name");
            final String number = data.getString("number");
            final String address = data.getString("address");
            final String sceneImage = data.getString("sceneImage");
            final String description = data.getString("description");
            final String url = data.getString("url");
            final Integer level = data.getInteger("level");
            final Double lng = data.getDouble("lng");
            final Double lat = data.getDouble("lat");
            final JSONArray polygonPoints = data.getJSONArray("polygonPoints");
            return doSaveMsOne(messageType, projectId, name, number,
                    lng, lat, address, sceneImage, url, level,
                    dataType, description, polygonPoints, pipelineId);
        }
    }


    @Transactional(rollbackFor = Exception.class, isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    public boolean doSaveMsMulti(Integer messageType, Integer projectId, Integer pipelineId, JSONArray data, Integer dataType) {
        final int size = data.size();
        AtomicInteger count = new AtomicInteger();
        switch (messageType) {
            case 1: {
                data.forEach(o -> {
                    final ObjectMapper objectMapper = new ObjectMapper();
                    final JSONObject jsonObject = objectMapper.convertValue(o, JSONObject.class);
                    final String number = jsonObject.getString("number");
                    final Double lng = jsonObject.getDouble("lng");
                    final Double lat = jsonObject.getDouble("lat");
                    final PileCard pileCard = new PileCard().setPipelineId(pipelineId).setLat(lat).setLng(lng).setSystemStakeNumber(number).setPileCardTypeId(dataType).setProjectId(projectId);
                    count.addAndGet(pileCardMapper.insert(pileCard));
                });
            }
            break;
            case 2: {
                data.forEach(o -> {
                    final ObjectMapper objectMapper = new ObjectMapper();
                    final JSONObject jsonObject = objectMapper.convertValue(o, JSONObject.class);
                    final String name = jsonObject.getString("name");
                    final String number = jsonObject.getString("number");
                    final Double lng = jsonObject.getDouble("lng");
                    final Double lat = jsonObject.getDouble("lat");
                    final GeneralFacilities generalFacilities = new GeneralFacilities()
                            .setPipelineId(pipelineId)
                            .setLat(lat)
                            .setLng(lng)
                            .setNumber(number)
                            .setName(name)
                            .setGeneralFacilitiesTypeId(dataType)
                            .setProjectId(projectId);
                    count.addAndGet(generalFacilitiesMapper.insert(generalFacilities));
                });
            }
            break;
            case 3: {
                data.forEach(o -> {
                    final ObjectMapper objectMapper = new ObjectMapper();
                    final JSONObject jsonObject = objectMapper.convertValue(o, JSONObject.class);
                    final String name = jsonObject.getString("name");
                    final String number = jsonObject.getString("number");
                    final JSONArray polygonPoints = jsonObject.getJSONArray("polygonPoints");
                    final HighConsequenceAreas highConsequenceAreas = new HighConsequenceAreas().setPipelineId(pipelineId).setPolygonPoints(polygonPoints).setNumber(number).setName(name).setHighConsequenceAreasTypeId(dataType).setProjectId(projectId);
                    count.addAndGet(highConsequenceAreasMapper.insert(highConsequenceAreas));
                });
            }
            break;
            case 4: {
                data.forEach(o -> {
                    final ObjectMapper objectMapper = new ObjectMapper();
                    final JSONObject jsonObject = objectMapper.convertValue(o, JSONObject.class);
                    final String name = jsonObject.getString("name");
                    final String number = jsonObject.getString("number");
                    final Double lng = jsonObject.getDouble("lng");
                    final Double lat = jsonObject.getDouble("lat");
                    final ConstructionUnits constructionUnits = new ConstructionUnits().setPipelineId(pipelineId).setLat(lat).setLng(lng).setNumber(number).setName(name).setConstructionTypeId(dataType).setProjectId(projectId);
                    count.addAndGet(constructionUnitsMapper.insert(constructionUnits));
                });
            }
            break;
            case 5: {
                data.forEach(o -> {
                    final ObjectMapper objectMapper = new ObjectMapper();
                    final JSONObject jsonObject = objectMapper.convertValue(o, JSONObject.class);
                    final String name = jsonObject.getString("name");
                    final String number = jsonObject.getString("number");
                    final Double lng = jsonObject.getDouble("lng");
                    final Double lat = jsonObject.getDouble("lat");
                    final Camera camera = new Camera().setPipelineId(pipelineId).setLat(lat).setLng(lng).setNumber(number).setName(name).setCameraTypeId(dataType).setProjectId(projectId);
                    count.addAndGet(cameraMapper.insert(camera));
                });
            }
            break;
            default: {
                log.error("信息类型错误...");
                return false;
            }
        }
        return size == count.get();
    }

    @Transactional(rollbackFor = Exception.class, isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
    public boolean doSaveMsOne(Integer messageType, Integer projectId, String name, String number,
                               Double lng, Double lat, String address, String sceneImage, String url, Integer level,
                               Integer typeId, String description, JSONArray polygonPoints, Integer pipelineId) {
        switch (messageType) {
            case 1: {
                final PileCard pileCard = new PileCard();
                pileCard.setPipelineId(pipelineId).setLat(lat).setLng(lng).setSystemStakeNumber(number).setDescription(description).setAddress(address).setSceneImage(sceneImage).setPileCardTypeId(typeId).setProjectId(projectId);
                return 1 == pileCardMapper.insert(pileCard);
            }
            case 2: {
                final GeneralFacilities generalFacilities = new GeneralFacilities();
                generalFacilities.setPipelineId(pipelineId).setLat(lat).setLng(lng).setNumber(number).setDescription(description).setAddress(address).setSceneImage(sceneImage).setName(name).setGeneralFacilitiesTypeId(typeId).setProjectId(projectId);
                return 1 == generalFacilitiesMapper.insert(generalFacilities);
            }
            case 3: {
                final HighConsequenceAreas highConsequenceAreas = new HighConsequenceAreas();
                highConsequenceAreas.setPipelineId(pipelineId).setPolygonPoints(polygonPoints).setLevel(level).setDescription(description).setNumber(number).setName(name).setHighConsequenceAreasTypeId(typeId).setProjectId(projectId);
                return 1 == highConsequenceAreasMapper.insert(highConsequenceAreas);
            }
            case 4: {
                final ConstructionUnits constructionUnits = new ConstructionUnits();
                constructionUnits.setPipelineId(pipelineId).setLat(lat).setLng(lng).setNumber(number).setDescription(description).setAddress(address).setSceneImage(sceneImage).setName(name).setConstructionTypeId(typeId).setProjectId(projectId);
                return 1 == constructionUnitsMapper.insert(constructionUnits);
            }
            case 5: {
                final Camera camera = new Camera();
                camera.setPipelineId(pipelineId).setLat(lat).setLng(lng).setNumber(number).setUrl(url).setDescription(description).setAddress(address).setName(name).setCameraTypeId(typeId).setProjectId(projectId);
                return 1 == cameraMapper.insert(camera);
            }
            default: {
                log.error("信息类型错误...");
                return false;
            }
        }
    }

    /**
     * 分页查询
     *
     * @param queryMo 参数模型
     * @return ModelMap
     */
    @Override
    public IPage<GeneralFacilities> searchListPage(QueryMo queryMo) {
        Map<Integer, String> pipelineMap = mapperModel.getPipelineMap(queryMo);
        Map<Integer, GeneralFacilitiesType> generalFacilitiesTypeMap = mapperModel.getGeneralFacilitiesTypeMap();
        IPage<GeneralFacilities> page = PageModel.getModelPage(queryMo, generalFacilitiesMapper);
        page.getRecords().forEach(generalFacilities -> {
            if (Objects.nonNull(generalFacilities.getLngLats())) {
                generalFacilities.setLngLatList(JSONArray.parseArray(generalFacilities.getLngLats()));
                generalFacilities.setLngLats(null);
            }
            final GeneralFacilitiesType generalFacilitiesType = generalFacilitiesTypeMap.get(generalFacilities.getGeneralFacilitiesTypeId());
            if (Objects.nonNull(generalFacilitiesTypeMap.get(generalFacilities.getGeneralFacilitiesTypeId()))) {
                generalFacilities.setGeneralFacilitiesTypeName(generalFacilitiesType.getName());
                final String icon = generalFacilitiesType.getIcon();
                if (Objects.nonNull(icon)) {
                    generalFacilities.setGeneralFacilitiesTypeIcon(ocsSimpleModel.getObjectUrl(icon));
                }
            }
            generalFacilities.setPipelineName(pipelineMap.get(generalFacilities.getPipelineId()));
            if (Objects.nonNull(generalFacilities.getSceneImage())) {
                generalFacilities.setSceneImage(ocsSimpleModel.getObjectUrl(generalFacilities.getSceneImage()));
            }
        });
        return page;
    }


    /**
     * 通过ID等参数查询一条数据
     *
     * @param queryMo 参数集[实体ID 与 项目ID, 数据状态等]
     * @return 单条记录结果
     */
    @Override
    public GeneralFacilities selectOne(QueryMo queryMo) {
        if (Objects.nonNull(queryMo.getEqMap().get("id"))) {
            GeneralFacilities generalFacilities = generalFacilitiesMapper.selectOne(new QueryWrapper<GeneralFacilities>().allEq(queryMo.getEqMap()));
            if (Objects.nonNull(generalFacilities) && Objects.nonNull(generalFacilities.getSceneImage())) {
                generalFacilities.setSceneImage(ocsSimpleModel.getObjectUrl(generalFacilities.getSceneImage()));
            }
            return generalFacilities;
        }
        return null;
    }

    /**
     * 插入一条数据
     *
     * @param operateMo 实体对象
     * @return 是否操作成功
     */
    @Override
    public boolean insert(OperateMo operateMo) {
        ObjectMapper objectMapper = new ObjectMapper();
        GeneralFacilities generalFacilities = objectMapper.convertValue(operateMo.getEntity(), GeneralFacilities.class);
        return 1 == generalFacilitiesMapper.insert(generalFacilities);
    }

    /**
     * 通过ID删除一条数据
     *
     * @param queryMo 参数集[实体ID 与 项目ID, 数据状态等]
     * @return 是否操作成功
     */
    @Override
    public boolean delete(QueryMo queryMo) {
        if (Objects.nonNull(queryMo.getEqMap().get("id"))) {
            return 1 == generalFacilitiesMapper.delete(new QueryWrapper<GeneralFacilities>().allEq(queryMo.getEqMap()));
        }
        return false;
    }

    /**
     * 插入一条数据
     *
     * @param operateMo 更新参数集
     * @return ModelMap
     */
    @Override
    public boolean update(OperateMo operateMo) {
        ObjectMapper objectMapper = new ObjectMapper();
        GeneralFacilities generalFacilities = objectMapper.convertValue(operateMo.getEntity(), GeneralFacilities.class);
        return 1 == generalFacilitiesMapper.update(generalFacilities, new QueryWrapper<GeneralFacilities>().allEq(operateMo.getEqMap()));
    }

    /**
     * 通过ID逻辑删除一条数据
     *
     * @param queryMo 参数集[实体ID 与 项目ID, 数据状态]
     * @return 是否操作成功
     */
    @Override
    public boolean logicallyDelete(QueryMo queryMo) {
        return 1 == generalFacilitiesMapper.update(
                new GeneralFacilities().setState(1),
                new QueryWrapper<GeneralFacilities>().allEq(queryMo.getEqMap())
        );
    }
}
